﻿
/**
 * Written by :
 * @author Floz
 * www.floz.fr || www.minuit4.fr
 */
package fr.tilzy.common
{
	import flash.display.DisplayObject;
	import flash.display.Sprite;
	import flash.geom.Point;
	import flash.geom.Rectangle;
	import fr.tilzy.common.objects.GameObject;
	import fr.tilzy.common.objects.Grid;
	import fr.tilzy.core.geom.IntPoint;
	import fr.tilzy.core.layers.Layer;
	import fr.tilzy.core.maps.Map;
	import fr.tilzy.core.paths.astar.Astar;
	import fr.tilzy.core.tiles.TileDatas;
	import fr.tilzy.utils.MapDatasConverter;
	
	public class World extends Sprite
	{
		
		// - PRIVATE VARIABLES -----------------------------------------------------------
		
		public static const DEFAULT_DATAS:Vector.<Vector.<TileDatas>> = MapDatasConverter.fromArray( [ [ 0, 0, 0, 0 ], [ 0, 0, 0, 0 ], [ 0, 0, 0, 0 ], [ 0, 0, 0, 0 ] ] );
		
		protected var _tileSize:int;
		protected var _map:Map;
		protected var _astar:Astar;
		protected var _world:Sprite;
		protected var _grid:Grid;
		protected var _gridContainer:Sprite;
		protected var _gridRect:Rectangle;
		
		protected var _layers:Object;
		
		protected var _showGrid:Boolean;
		
		// - PUBLIC VARIABLES ------------------------------------------------------------
		
		// - CONSTRUCTOR -----------------------------------------------------------------
		
		public function World( tileSize:int = 32, datas:Vector.<Vector.<TileDatas>> = null ) 
		{
			this._tileSize = tileSize;
			
			if ( datas == null )
				datas = DEFAULT_DATAS;
			
			_gridContainer = new Sprite();
			
			_map = new Map( datas );
			_astar = new Astar( _map );
			
			_world = new Sprite();
			addChild( _world );
			
			_layers = { };
		}
		
		// - EVENTS HANDLERS -------------------------------------------------------------
		
		// - PRIVATE METHODS -------------------------------------------------------------
		
		// - PUBLIC METHODS --------------------------------------------------------------
		
		/**
		 * Renvoie une série de points correspondant aux tiles de la map (et non aux coordonnées)
		 * à emprunter pour arriver à destination.
		 * Le chemin renvoyé est toujours le plus court.
		 * @param	start	Point	Le point de départ.
		 * @param	end	Point	Le point d'arriver.
		 * @return	Vector.<IntPoint>	Le vecteur contenant les points du parcours.
		 */
		public function findPath( start:Point, end:Point ):Vector.<IntPoint>
		{
			return _astar.findPath( start, end );
		}
		
		/**
		 * 
		 * @param	id
		 * @param	depth
		 */
		public function addLayer( id:String ):void
		{
			var layer:Layer = new Layer();
			_layers[ id ] = layer;
			_world.addChild( layer );
		}
		
		/**
		 * 
		 * @param	id
		 */
		public function removeLayer( id:String ):void
		{
			var layer:Layer = _layers[ id ];
			if ( layer == null )
				return;			
			
			_world.removeChild( layer );
			
			delete _layers[ id ];
			trace( "World.removeLayer : CHECK ICI SI BIEN CLEANE => " + _layers[ id ] );
		}
		
		public function getLayer( id:String ):Layer
		{
			return _layers[ id ] as Layer;
		}
		
		/**
		 * 
		 * @param	object
		 * @param	layerId
		 */
		public function addObject( object:GameObject, layerId:String ):void
		{
			var layer:Layer = _layers[ layerId ];
			if ( layer == null )
				return;
			
			layer.addObject( object );
		}
		
		public function dispose():void
		{
			_map.dispose();
			_map = null;
			
			_astar.dispose();
			_astar = null;
			
			_grid.dispose();
			_grid = null;
			_gridContainer = null;
			_gridRect = null;
			
			var layer:Layer;
			var id:String;
			for ( id in _layers )
			{
				layer = _layers[ id ];
				_world.removeChild( layer );
				layer.dispose();
			}
			_layers = null;
			
			removeChild( _world );
			_world = null;
		}
		
		// - GETTERS & SETTERS -----------------------------------------------------------
		
		public function get datas():Vector.<Vector.<TileDatas>> { return _map.datas; }
		
		public function set datas( value:Vector.<Vector.<TileDatas>> ):void
		{
			_map.datas = value;
			_astar.update();
			
			if ( _grid )
				_grid.refresh();
		}
		
		public function get tileSize():int { return _tileSize; }
		
		public function set tileSize(value:int):void 
		{
			_tileSize = value;
		}
		
		public function get showGrid():Boolean { return _showGrid; }
		
		public function set showGrid(value:Boolean):void 
		{
			_showGrid = value;
			
			if ( _grid )
			{
				if ( _showGrid )
				{
					_grid.cacheAsBitmap = true;
					addChildAt( _gridContainer, 0 );
				}
				else
				{
					_grid.cacheAsBitmap = false;
					if ( _gridContainer.parent ) removeChild( _gridContainer );
				}
			}
		}
		
		public function get worldWidth():Number { return _gridRect.width || super.width; }
		
		public function get worldHeight():Number { return _gridRect.height || super.height; }
		
		public function get map():Map { return _map; }
		
	}
	
}